//===--- CGFloat.swift.gyb ------------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

%{

from SwiftIntTypes import all_integer_types

# Number of bits in the Builtin.Word type
word_bits = int(CMAKE_SIZEOF_VOID_P) * 8

}%

@_exported import CoreGraphics
import Darwin

@_fixed_layout
public struct CGFloat {
#if arch(i386) || arch(arm)
  /// The native type used to store the CGFloat, which is Float on
  /// 32-bit architectures and Double on 64-bit architectures.
  public typealias NativeType = Float
#elseif arch(x86_64) || arch(arm64)
  /// The native type used to store the CGFloat, which is Float on
  /// 32-bit architectures and Double on 64-bit architectures.
  public typealias NativeType = Double
#endif

  @_transparent public init() {
    self.native = 0.0
  }

  @_transparent public init(_ value: Float) {
    self.native = NativeType(value)
  }

  @_transparent public init(_ value: Double) {
    self.native = NativeType(value)
  }

#if !os(Windows) && (arch(i386) || arch(x86_64))
  @_transparent public init(_ value: Float80) {
    self.native = NativeType(value)
  }
#endif

  @_transparent public init(_ value: CGFloat) {
    self.native = value.native
  }

% for src_ty in all_integer_types(word_bits):
  @_transparent public init(_ value: ${src_ty.stdlib_name}) {
    self.native = NativeType(value)
  }

% end

  /// The native value.
  public var native: NativeType
}

@_transparent extension CGFloat : BinaryFloatingPoint {

  public typealias RawSignificand = UInt
  public typealias Exponent = Int

  public static var exponentBitCount: Int {
    return NativeType.exponentBitCount
  }

  public static var significandBitCount: Int {
    return NativeType.significandBitCount
  }

  //  Conversions to/from integer encoding.  These are not part of the
  //  BinaryFloatingPoint prototype because there's no guarantee that an
  //  integer type of the same size actually exists (e.g. Float80).
  public var bitPattern: UInt {
    return UInt(native.bitPattern)
  }

  public init(bitPattern: UInt) {
    native = NativeType(bitPattern: UInt${word_bits}(bitPattern))
  }

  public var sign: FloatingPointSign {
    return native.sign
  }

  public var exponentBitPattern: UInt {
    return native.exponentBitPattern
  }

  public var significandBitPattern: UInt {
    return UInt(native.significandBitPattern)
  }

  public init(sign: FloatingPointSign,
              exponentBitPattern: UInt,
              significandBitPattern: UInt) {
    native = NativeType(sign: sign,
      exponentBitPattern: exponentBitPattern,
      significandBitPattern: NativeType.RawSignificand(significandBitPattern))
  }

  public init(nan payload: RawSignificand, signaling: Bool) {
    native = NativeType(nan: NativeType.RawSignificand(payload),
                        signaling: signaling)
  }

  public static var infinity: CGFloat {
    return CGFloat(NativeType.infinity)
  }

  public static var nan: CGFloat {
    return CGFloat(NativeType.nan)
  }

  public static var signalingNaN: CGFloat {
    return CGFloat(NativeType.signalingNaN)
  }
  
  @available(*, unavailable, renamed: "nan")
  public static var quietNaN: CGFloat {
    fatalError("unavailable")
  }

  public static var greatestFiniteMagnitude: CGFloat {
    return CGFloat(NativeType.greatestFiniteMagnitude)
  }

  public static var pi: CGFloat {
    return CGFloat(NativeType.pi)
  }

  public var ulp: CGFloat {
    return CGFloat(native.ulp)
  }

  public static var leastNormalMagnitude: CGFloat {
    return CGFloat(NativeType.leastNormalMagnitude)
  }

  public static var leastNonzeroMagnitude: CGFloat {
    return CGFloat(NativeType.leastNonzeroMagnitude)
  }

  public var exponent: Int {
    return native.exponent
  }

  public var significand: CGFloat {
    return CGFloat(native.significand)
  }

  public init(sign: FloatingPointSign, exponent: Int, significand: CGFloat) {
    native = NativeType(sign: sign,
      exponent: exponent, significand: significand.native)
  }

  public var nextUp: CGFloat {
    return CGFloat(native.nextUp)
  }

  public var nextDown: CGFloat {
    return CGFloat(native.nextDown)
  }

  public static func abs(_ x: CGFloat) -> CGFloat {
    return CGFloat(NativeType.abs(x.native))
  }

  public mutating func negate() {
    native.negate()
  }

  public mutating func add(_ other: CGFloat) {
    native.add(other.native)
  }

  public mutating func subtract(_ other: CGFloat) {
    native.subtract(other.native)
  }

  public mutating func multiply(by other: CGFloat) {
    native.multiply(by: other.native)
  }

  public mutating func divide(by other: CGFloat) {
    native.divide(by: other.native)
  }

  public mutating func formTruncatingRemainder(dividingBy other: CGFloat) {
    native.formTruncatingRemainder(dividingBy: other.native)
  }

  /*  TODO: Need to call C sqrt and fma or llvm sqrt and fma intrinsics
   *  for these to be implemented on the underlying types.
  public mutating func formRemainder(dividingBy other: CGFloat) {
    native.formRemainder(dividingBy: other.native)
  }

  public mutating func formSquareRoot( ) {
    native.formSquareRoot( )
  }

  public mutating func addProduct(_ lhs: CGFloat, _ rhs: CGFloat) {
    native.addProduct(lhs.native, rhs.native)
  }
  */

  public func isEqual(to other: CGFloat) -> Bool {
    return self.native.isEqual(to: other.native)
  }

  public func isLess(than other: CGFloat) -> Bool {
    return self.native.isLess(than: other.native)
  }

  public func isLessThanOrEqualTo(_ other: CGFloat) -> Bool {
    return self.native.isLessThanOrEqualTo(other.native)
  }

  public var isNormal:  Bool {
    return native.isNormal
  }

  public var isFinite:  Bool {
    return native.isFinite
  }

  public var isZero:  Bool {
    return native.isZero
  }

  public var isSubnormal:  Bool {
    return native.isSubnormal
  }

  public var isInfinite:  Bool {
    return native.isInfinite
  }

  public var isNaN:  Bool {
    return native.isNaN
  }

  public var isSignalingNaN: Bool {
    return native.isSignalingNaN
  }

  @available(*, unavailable, renamed: "isSignalingNaN")
  public var isSignaling: Bool {
    fatalError("unavailable")
  }

  public var isCanonical: Bool {
    return true
  }

  public var floatingPointClass: FloatingPointClassification {
    return native.floatingPointClass
  }

  public var binade: CGFloat {
    return CGFloat(native.binade)
  }

  public var significandWidth: Int {
    return native.significandWidth
  }

  /// Create an instance initialized to `value`.
  public init(floatLiteral value: NativeType) {
    native = value
  }

  /// Create an instance initialized to `value`.
  public init(integerLiteral value: Int) {
    native = NativeType(value)
  }
}

extension CGFloat {
  @available(*, unavailable, renamed: "leastNormalMagnitude")
  public static var min: CGFloat {
    fatalError("unavailable")
  }

  @available(*, unavailable, renamed: "greatestFiniteMagnitude")
  public static var max: CGFloat {
    fatalError("unavailable")
  }
}

@available(*, unavailable, renamed: "CGFloat.leastNormalMagnitude")
public var CGFLOAT_MIN: CGFloat {
  fatalError("unavailable")
}

@available(*, unavailable, renamed: "CGFloat.greatestFiniteMagnitude")
public var CGFLOAT_MAX: CGFloat {
  fatalError("unavailable")
}

extension CGFloat : CustomReflectable {
  /// Returns a mirror that reflects `self`.
  public var customMirror: Mirror {
    return Mirror(reflecting: native)
  }
}

@_transparent extension CGFloat : CustomStringConvertible {
  /// A textual representation of `self`.
  public var description: String {
    return native.description
  }
}

@_transparent extension CGFloat : Hashable {
  /// The hash value.
  ///
  /// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`
  ///
  /// - Note: the hash value is not guaranteed to be stable across
  ///   different invocations of the same program.  Do not persist the
  ///   hash value across program runs.
  public var hashValue: Int {
    return native.hashValue
  }
}

% for dst_ty in all_integer_types(word_bits):

@_transparent extension ${dst_ty.stdlib_name} {
  public init(_ value: CGFloat) {
    self = ${dst_ty.stdlib_name}(value.native)
  }
}

% end


@_transparent extension Double {
  public init(_ value: CGFloat) {
    self = Double(value.native) 
  }
}

@_transparent extension Float {
  public init(_ value: CGFloat) {
    self = Float(value.native) 
  }
}

//===----------------------------------------------------------------------===//
// Standard Operator Table
//===----------------------------------------------------------------------===//

//  TODO: These should not be necessary, since they're already provided by
//  <T: FloatingPoint>, but in practice they are currently needed to
//  disambiguate overloads.  We should find a way to remove them, either by
//  tweaking the overload resolution rules, or by removing the other
//  definitions in the standard lib, or both.

@_transparent
public func +(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
  return lhs.adding(rhs)
}

@_transparent
public func -(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
  return lhs.subtracting(rhs)
}

@_transparent
public func *(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
  return lhs.multiplied(by: rhs)
}

@_transparent
public func /(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
  return lhs.divided(by: rhs)
}

@_transparent
public func +=(lhs: inout CGFloat, rhs: CGFloat) {
  lhs.add(rhs)
}

@_transparent
public func -=(lhs: inout CGFloat, rhs: CGFloat) {
  lhs.subtract(rhs)
}

@_transparent
public func *=(lhs: inout CGFloat, rhs: CGFloat) {
  lhs.multiply(by: rhs)
}

@_transparent
public func /=(lhs: inout CGFloat, rhs: CGFloat) {
  lhs.divide(by: rhs)
}

//===----------------------------------------------------------------------===//
// Strideable Conformance
//===----------------------------------------------------------------------===//

@_transparent extension CGFloat : Strideable {
  /// Returns a stride `x` such that `self.advanced(by: x)` approximates
  /// `other`.
  ///
  /// - Complexity: O(1).
  @_transparent
  public func distance(to other: CGFloat) -> CGFloat {
    return CGFloat(other.native - self.native)
  }

  /// Returns a `Self` `x` such that `self.distance(to: x)` approximates
  /// `n`.
  ///
  /// - Complexity: O(1).
  @_transparent
  public func advanced(by amount: CGFloat) -> CGFloat {
    return CGFloat(self.native + amount.native)
  }
}

//===----------------------------------------------------------------------===//
// Deprecated operators
//===----------------------------------------------------------------------===//

@_transparent
@available(*, unavailable, message: "use += 1")
@discardableResult
public prefix func ++(rhs: inout CGFloat) -> CGFloat {
  fatalError("++ is not available")
}

@_transparent
@available(*, unavailable, message: "use -= 1")
@discardableResult
public prefix func --(rhs: inout CGFloat) -> CGFloat {
  fatalError("-- is not available")
}

@_transparent
@available(*, unavailable, message: "use += 1")
@discardableResult
public postfix func ++(lhs: inout CGFloat) -> CGFloat {
  fatalError("++ is not available")
}

@_transparent
@available(*, unavailable, message: "use -= 1")
@discardableResult
public postfix func --(lhs: inout CGFloat) -> CGFloat {
  fatalError("-- is not available")
}

@_transparent
@available(*, unavailable, message: "Use truncatingRemainder instead")
public func %(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
  fatalError("% is not available.")
}

@_transparent
@available(*, unavailable, message: "Use formTruncatingRemainder instead")
public func %=(lhs: inout CGFloat, rhs: CGFloat) {
  fatalError("%= is not available.")
}

//===----------------------------------------------------------------------===//
// tgmath
//===----------------------------------------------------------------------===//

@_transparent
public func acos(_ x: CGFloat) -> CGFloat {
  return CGFloat(acos(x.native))
}

@_transparent
public func cos(_ x: CGFloat) -> CGFloat {
  return CGFloat(cos(x.native))
}

@_transparent
public func sin(_ x: CGFloat) -> CGFloat {
  return CGFloat(sin(x.native))
}

@_transparent
public func asin(_ x: CGFloat) -> CGFloat {
  return CGFloat(asin(x.native))
}

@_transparent
public func atan(_ x: CGFloat) -> CGFloat {
  return CGFloat(atan(x.native))
}

@_transparent
public func tan(_ x: CGFloat) -> CGFloat {
  return CGFloat(tan(x.native))
}

@_transparent
public func acosh(_ x: CGFloat) -> CGFloat {
  return CGFloat(acosh(x.native))
}

@_transparent
public func asinh(_ x: CGFloat) -> CGFloat {
  return CGFloat(asinh(x.native))
}

@_transparent
public func atanh(_ x: CGFloat) -> CGFloat {
  return CGFloat(atanh(x.native))
}

@_transparent
public func cosh(_ x: CGFloat) -> CGFloat {
  return CGFloat(cosh(x.native))
}

@_transparent
public func sinh(_ x: CGFloat) -> CGFloat {
  return CGFloat(sinh(x.native))
}

@_transparent
public func tanh(_ x: CGFloat) -> CGFloat {
  return CGFloat(tanh(x.native))
}

@_transparent
public func exp(_ x: CGFloat) -> CGFloat {
  return CGFloat(exp(x.native))
}

@_transparent
public func exp2(_ x: CGFloat) -> CGFloat {
  return CGFloat(exp2(x.native))
}

@_transparent
public func expm1(_ x: CGFloat) -> CGFloat {
  return CGFloat(expm1(x.native))
}

@_transparent
public func log(_ x: CGFloat) -> CGFloat {
  return CGFloat(log(x.native))
}

@_transparent
public func log10(_ x: CGFloat) -> CGFloat {
  return CGFloat(log10(x.native))
}

@_transparent
public func log2(_ x: CGFloat) -> CGFloat {
  return CGFloat(log2(x.native))
}

@_transparent
public func log1p(_ x: CGFloat) -> CGFloat {
  return CGFloat(log1p(x.native))
}

@_transparent
public func logb(_ x: CGFloat) -> CGFloat {
  return CGFloat(logb(x.native))
}

@_transparent
public func cbrt(_ x: CGFloat) -> CGFloat {
  return CGFloat(cbrt(x.native))
}

@_transparent
public func erf(_ x: CGFloat) -> CGFloat {
  return CGFloat(erf(x.native))
}

@_transparent
public func erfc(_ x: CGFloat) -> CGFloat {
  return CGFloat(erfc(x.native))
}

@_transparent
public func tgamma(_ x: CGFloat) -> CGFloat {
  return CGFloat(tgamma(x.native))
}

@_transparent
public func fabs(_ x: CGFloat) -> CGFloat {
  return CGFloat(fabs(x.native))
}

@_transparent
public func sqrt(_ x: CGFloat) -> CGFloat {
  return CGFloat(sqrt(x.native))
}

@_transparent
public func ceil(_ x: CGFloat) -> CGFloat {
  return CGFloat(ceil(x.native))
}

@_transparent
public func floor(_ x: CGFloat) -> CGFloat {
  return CGFloat(floor(x.native))
}

@_transparent
public func nearbyint(_ x: CGFloat) -> CGFloat {
  return CGFloat(nearbyint(x.native))
}

@_transparent
public func rint(_ x: CGFloat) -> CGFloat {
  return CGFloat(rint(x.native))
}

@_transparent
public func round(_ x: CGFloat) -> CGFloat {
  return CGFloat(round(x.native))
}

@_transparent
public func trunc(_ x: CGFloat) -> CGFloat {
  return CGFloat(trunc(x.native))
}

@_transparent
public func atan2(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(atan2(lhs.native, rhs.native))
}

@_transparent
public func hypot(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(hypot(lhs.native, rhs.native))
}

@_transparent
public func pow(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(pow(lhs.native, rhs.native))
}

@_transparent
public func fmod(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(fmod(lhs.native, rhs.native))
}

@_transparent
public func remainder(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(remainder(lhs.native, rhs.native))
}

@_transparent
public func copysign(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(copysign(lhs.native, rhs.native))
}

@_transparent
public func nextafter(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(nextafter(lhs.native, rhs.native))
}

@_transparent
public func fdim(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(fdim(lhs.native, rhs.native))
}

@_transparent
public func fmax(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(fmax(lhs.native, rhs.native))
}

@_transparent
public func fmin(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(fmin(lhs.native, rhs.native))
}

@_transparent
@available(*, unavailable, message: "use the floatingPointClass property.")
public func fpclassify(_ x: CGFloat) -> Int {
  fatalError("unavailable")
}

@available(*, unavailable, message: "use the isNormal property.")
public func isnormal(_ value: CGFloat) -> Bool { return value.isNormal }

@available(*, unavailable, message: "use the isFinite property.")
public func isfinite(_ value: CGFloat) -> Bool { return value.isFinite }

@available(*, unavailable, message: "use the isInfinite property.")
public func isinf(_ value: CGFloat) -> Bool { return value.isInfinite }

@available(*, unavailable, message: "use the isNaN property.")
public func isnan(_ value: CGFloat) -> Bool { return value.isNaN }

@available(*, unavailable, message: "use the sign property.")
public func signbit(_ value: CGFloat) -> Int { return value.sign.rawValue }

@_transparent
public func modf(_ x: CGFloat) -> (CGFloat, CGFloat) {
  let (ipart, fpart) = modf(x.native)
  return (CGFloat(ipart), CGFloat(fpart))
}

@_transparent
public func ldexp(_ x: CGFloat, _ n: Int) -> CGFloat {
  return CGFloat(ldexp(x.native, n))
}

@_transparent
public func frexp(_ x: CGFloat) -> (CGFloat, Int) {
  let (frac, exp) = frexp(x.native)
  return (CGFloat(frac), exp)
}

@_transparent
public func ilogb(_ x: CGFloat) -> Int {
  return ilogb(x.native)
}

@_transparent
public func scalbn(_ x: CGFloat, _ n: Int) -> CGFloat {
  return CGFloat(scalbn(x.native, n))
}

@_transparent
public func lgamma(_ x: CGFloat) -> (CGFloat, Int) {
  let (value, sign) = lgamma(x.native)
  return (CGFloat(value), sign)
}

@_transparent
public func remquo(_ x: CGFloat, _ y: CGFloat) -> (CGFloat, Int) {
  let (rem, quo) = remquo(x.native, y.native)
  return (CGFloat(rem), quo)
}

@_transparent
public func nan(_ tag: String) -> CGFloat {
  return CGFloat(nan(tag) as CGFloat.NativeType)
}

@_transparent
public func fma(_ x: CGFloat, _ y: CGFloat, _ z: CGFloat) -> CGFloat {
  return CGFloat(fma(x.native, y.native, z.native))
}

@_transparent
public func j0(_ x: CGFloat) -> CGFloat {
  return CGFloat(j0(Double(x.native)))
}

@_transparent
public func j1(_ x: CGFloat) -> CGFloat {
  return CGFloat(j1(Double(x.native)))
}

@_transparent
public func jn(_ n: Int, _ x: CGFloat) -> CGFloat {
  return CGFloat(jn(n, Double(x.native)))
}

@_transparent
public func y0(_ x: CGFloat) -> CGFloat {
  return CGFloat(y0(Double(x.native)))
}

@_transparent
public func y1(_ x: CGFloat) -> CGFloat {
  return CGFloat(y1(Double(x.native)))
}

@_transparent
public func yn(_ n: Int, _ x: CGFloat) -> CGFloat {
  return CGFloat(yn(n, Double(x.native)))
}

@_transparent
extension CGFloat : _CVarArgPassedAsDouble, _CVarArgAligned {
  /// Transform `self` into a series of machine words that can be
  /// appropriately interpreted by C varargs
  public var _cVarArgEncoding: [Int] {
    return native._cVarArgEncoding
  }

  /// Return the required alignment in bytes of 
  /// the value returned by `_cVarArgEncoding`.
  public var _cVarArgAlignment: Int { 
    return native._cVarArgAlignment
  }
}
